﻿using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace Ahresty.Entity
{
    /// <summary>
    /// 材料メッシュデータの要素を表すクラス
    /// </summary>
    internal class Unit
    {
        #region Properties

        internal short X { get; set; }

        internal short Y { get; set; }

        internal short Z { get; set; }

        internal double OccupiedRatio { get; set; }

        internal byte MaterialID { get; set; }

        #endregion


        #region Methods

        /// <summary>
        /// 各占有率で生成したin3dファイルから要素の占有率を算出
        /// </summary>
        /// <param name="units">要素情報の集合</param>
        /// <param name="in3dFiles">各占有率で生成したin3dファイルのパス</param>
        /// <param name="targetMaterialID">対象材料番号</param>
        internal static Unit[] GetUnitsInfo(Unit[] units, string[] in3dFiles, byte targetMaterialID)
        {
            List<Unit> unitList = new List<Unit>();

            foreach (string in3dFile in in3dFiles)
            {
                IN3DData in3dData = new IN3DData(in3dFile, targetMaterialID);
                double occupiedRatio = double.Parse("0." + new FileInfo(in3dFile).Name.Split('.').First());
                foreach (Unit u in units)
                    unitList.Add(new Unit { X = u.X, Y = u.Y, Z = u.Z, OccupiedRatio = occupiedRatio, MaterialID = in3dData.Data[u.X, u.Y, u.Z], });
            }

            var tempUnitList = (from u in unitList
                                where u.MaterialID == targetMaterialID
                                group u by new { u.X, u.Y, u.Z, } into g
                                select new Unit { X = g.Key.X, Y = g.Key.Y, Z = g.Key.Z, OccupiedRatio = g.Max(u => u.OccupiedRatio), }).Union(
                               from u in unitList
                               where u.MaterialID != targetMaterialID
                               group u by new { u.X, u.Y, u.Z, } into g
                               select new Unit { X = g.Key.X, Y = g.Key.Y, Z = g.Key.Z, OccupiedRatio = g.Min(u => u.OccupiedRatio), });
            var tempUnitList2 = from u in tempUnitList
                                group u by new { u.X, u.Y, u.Z, } into g
                                select new { X = g.Key.X, Y = g.Key.Y, Z = g.Key.Z, OccupiedRatio = g.Average(u => u.OccupiedRatio), Count = g.Count(), };

            return (from u in tempUnitList2
                    select new Unit { X = u.X, Y = u.Y, Z = u.Z, OccupiedRatio = u.Count == 1 ? u.OccupiedRatio / 2 : u.OccupiedRatio, }).ToArray();
        }

        #endregion
    }
}